package com.ts.manager;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import android.os.Handler;
import android.util.Log;

import com.alibaba.sdk.android.oss.ClientConfiguration;
import com.alibaba.sdk.android.oss.ClientException;
import com.alibaba.sdk.android.oss.OSS;
import com.alibaba.sdk.android.oss.OSSClient;
import com.alibaba.sdk.android.oss.ServiceException;
import com.alibaba.sdk.android.oss.callback.OSSCompletedCallback;
import com.alibaba.sdk.android.oss.common.OSSLog;
import com.alibaba.sdk.android.oss.common.auth.OSSCredentialProvider;
import com.alibaba.sdk.android.oss.common.auth.OSSPlainTextAKSKCredentialProvider;
import com.alibaba.sdk.android.oss.model.GetObjectRequest;
import com.alibaba.sdk.android.oss.model.GetObjectResult;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.HttpHandler;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
import com.lidroid.xutils.http.client.HttpRequest;
import com.rio.core.L;
import com.rio.core.S;
import com.rio.core.U;
import com.rio.helper.file.FileHelper;
import com.rio.helper.json.G;
import com.rio.layout.TaskManager;
import com.rio.layout.view.SimpleTask;
import com.ts.api.DownloadApi;
import com.ts.data.APIExecuteHADAction;
import com.ts.data.Ad;
import com.ts.data.Li;
import com.ts.host.APP;
import com.ts.host.Event;
import com.ts.host.Event.AdTips;

import de.greenrobot.event.EventBus;

public class DownloadMananger {



	private static final int DELYED = 10 * 60 * 1000;//10分后执行一次
	private static final int RADMON = 5 * 60 * 1000;//5分钟的随机数浮动

	private Handler handler = new Handler();
	private  SimpleTask mDownTask;
	
	private static DownloadMananger mDownloadMananger;
	
	
	public static DownloadMananger getInstance(){
		if(mDownloadMananger == null){
			mDownloadMananger = new DownloadMananger();
		}
		return mDownloadMananger;
	}
	

	
	/**
	 * 马上下载，并开始定时器检测
	 */
	
	public  void postDelay() {
		getDownload();
		sendMessageDelayed();
	}
	
	/**
	 * 马上下载
	 */
	public  void postNow(){
		getDownload();
	}
	

	private void sendMessageDelayed(){
		if(handler != null){
			handler.postDelayed(runnable, U.getDownCountRandom(RADMON,DELYED));
		}
	}
	
    
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            // handler自带方法实现定时器
            try {
            	getDownload();
             	sendMessageDelayed();
             } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };
	
	
	/**
	 * 广告接口数据
	 * @return
	 */
	private  SimpleTask getDownTask() {
		if (U.isNull(mDownTask)) {
			
			mDownTask = new SimpleTask() {

				public Object onBGThread(Object... params) throws Exception {
					
					APIExecuteHADAction action = null;
					if (U.size(1, params)) {
						String response = U.findById(params, 0);
						 action = G.toObject(response,
								APIExecuteHADAction.class);
					
					}
					return action;
				}
			
				
				@Override
				public void onUIThread(Object data, Object... params)
						throws Exception {
					// TODO Auto-generated method stub
					super.onUIThread(data, params);
					if(data != null && data instanceof APIExecuteHADAction){
						APIExecuteHADAction action = (APIExecuteHADAction)data;
						if (U.notNull(action) && U.notNull(action.data) && U.notNull(action.data.get(0))) {
							Ad ad = action.data.get(0);
							ad.objectKey = ad.hostadid + ".zip";
							postTips("最新广告 ："+ad.version);							
							if (MachineManager.getInstance().compareDateKey( ad.version)) {
//								startDownLoadZip(ad);
								startDownloadWithOSS(ad);
							}
						}else{
							postTips("最新广告 ：无");
						}
					}
				}
				
				@Override
				public void onException(Exception exception, Object... params) {
					// TODO Auto-generated method stub
					super.onException(exception, params);
					
				
				}

			};

		}
		return mDownTask;

	}
	
	/**
	 * 开始从啊里云下载
	 * @param ad
	 */
	private void startDownloadWithOSS(Ad ad){
		if(ad != null){
			OssDownloadMananger.getInstance().asyncGetObjectRangeSample(ad.buckname, ad.objectKey, 0, ad.zipsize,new OSSCompletedCallback<GetObjectRequest, GetObjectResult>() {
	            @Override
	            public void onSuccess(GetObjectRequest request, GetObjectResult result) {
	                // 请求成功
	                InputStream inputStream = result.getObjectContent();

	                byte[] buffer = new byte[2048];
	                int len;

	                try {
	                    while ((len = inputStream.read(buffer)) != -1) {
	                        // 处理下载的数据
	                        Log.d("asyncGetObjectSample", "read length: " + len);
	                    }
	                    Log.d("asyncGetObjectSample", "download success.");
	                } catch (IOException e) {
	                    e.printStackTrace();
	                }
	            }

	            @Override
	            public void onFailure(GetObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
	                // 请求异常
	                if (clientExcepion != null) {
	                    // 本地异常如网络异常等
	                    clientExcepion.printStackTrace();
	                }
	                if (serviceException != null) {
	                    // 服务异常
	                    Log.e("ErrorCode", serviceException.getErrorCode());
	                    Log.e("RequestId", serviceException.getRequestId());
	                    Log.e("HostId", serviceException.getHostId());
	                    Log.e("RawMessage", serviceException.getRawMessage());
	                }
	            }
	        });
		}
	}
	
	
	
	private void startDownLoadZip(Ad ad){
		L.i("正下载广告 ："+ad.version);
		APP.getInstance().isDownloading = true;
		File zip = FileHelper.getSDCardFile(
				ad.version + ".zip");
		HttpUtils http = new HttpUtils();
		HttpHandler handler = http.download(
				ad.zipurl,
				zip.getAbsolutePath(),
				true, // 如果目标文件存在，接着未完成的部分继续下载。服务器不支持RANGE时将从新下载。
				true, // 如果从请求返回信息中获取到文件名，下载完成后自动重命名。
				new DownloadCallBack(ad,zip));
	}
	
	private  class DownloadCallBack extends RequestCallBack<File>{
		
		private Ad ad;
		private File zip;
		
	
		public DownloadCallBack(Ad ad,File zip) {
			super();
			this.ad = ad;
			this.zip = zip;
		}

		@Override
		public void onSuccess(ResponseInfo<File> responseInfo) {
			// TODO Auto-generated method stub			
			L.i("广告下载成功");
			TaskManager.getInstance().async(getZipTask(),ad,responseInfo.result);
		}

		@Override
		public void onFailure(HttpException error, String msg) {
			// TODO Auto-generated method stub
			APP.getInstance().isDownloading = false;
			if(zip != null){
				zip.delete();
			}
			L.i("广告下载失败");
		}
		
		
	}

	private  SimpleTask mZipTask;

	private  SimpleTask getZipTask() {
		if (U.isNull(mZipTask)) {
			mZipTask = new SimpleTask() {

				public Object onBGThread(Object... params) throws Exception {
					if (U.size(2, params)) {
						Ad ad = U.findById(params, 0);
						File file = U.findById(params, 1);
						String last = MachineManager.getInstance().getDateKey();

						if (upZipFile(file,
								FileHelper.getSDCardFile(ad.version))) {							
							MachineManager.getInstance().setDateKey(ad.version);
							EventBus.getDefault().post(
									new Event.DownloadUpdate());
							if(U.notNull(last))FileHelper.delete(last);
							postTips("广告更换成功");
						}else{					
							postTips("广告解压失败");
						}
						file.delete();
					}
					APP.getInstance().isDownloading = false;
					return null;

				};

				public void onException(Exception exception, Object... params) {
					APP.getInstance().isDownloading = false;
				};

			};
		}
		return mZipTask;
	}
	
	private  void postTips(String msg){
		AdTips event = new AdTips();
		event.text = msg;
		EventBus.getDefault().post(event);
	}

	private  void getDownload() {
		
		if(APP.getInstance().isDownloading){
			postTips("当前广告正在下载，请稍候重试");
			return;
		}
		
		String key = MachineManager.getInstance().getDateKey();
		if(U.notNull(key)){
			postTips("当前广告 ："+key);
		}else{
			postTips("当前广告 ：无");

		}

//		DownloadApi api = new DownloadApi();
//		String machineID = null;
//		if(MachineManager.getInstance().getMachine() != null){
//			machineID =  MachineManager.getInstance().getMachine().machineID;
//		}
//		api.id = machineID;
//		api.time = U.toString(System.currentTimeMillis());
//		String url = api.getRequest();
		
		String url = "http://api.heshuiba.com.cn/water/APIExecuteHADAction?id=392&type=10";
		HttpUtils http = new HttpUtils();
		http.send(HttpRequest.HttpMethod.GET, url,
				new RequestCallBack<String>() {

					@Override
					public void onSuccess(ResponseInfo<String> responseInfo) {
						if(responseInfo != null){
							L.i(responseInfo.result);
							TaskManager.getInstance().async(
								getDownTask(),responseInfo.result);
						}
					}

					@Override
					public void onFailure(HttpException error, String msg) {
						
					}
				});

	}

	/**
	 * 解压缩功能. 将zipFile文件解压到folderPath目录下.
	 * 
	 * @throws Exception
	 */
	public  boolean upZipFile(File zipFile, File desDir) {
		if (!desDir.exists()) {
			desDir.mkdirs();
		}
		try {
			ZipFile zfile = new ZipFile(zipFile);
			Enumeration zList = zfile.entries();
			ZipEntry ze = null;
			byte[] buf = new byte[1024];
			while (zList.hasMoreElements()) {
				ze = (ZipEntry) zList.nextElement();
				if (ze.isDirectory()) {
					String dirstr = desDir.getAbsolutePath() + S.DOCUMENT
							+ ze.getName();
					// dirstr.trim();
					dirstr = new String(dirstr.getBytes("8859_1"), "GB2312");
					File f = new File(dirstr);
					f.mkdir();
					continue;
				}
				OutputStream os = new BufferedOutputStream(
						new FileOutputStream(getRealFileName(
								desDir.getAbsolutePath(), ze.getName())));
				InputStream is = new BufferedInputStream(
						zfile.getInputStream(ze));
				int readLen = 0;
				while ((readLen = is.read(buf, 0, 1024)) != -1) {
					os.write(buf, 0, readLen);
				}
				is.close();
				os.close();
			}
			zfile.close();
		} catch (Exception e) {
			L.e(e);
			return false;
		}
		return true;
	}

	public  File getRealFileName(String baseDir, String absFileName) {
		String[] dirs = absFileName.split("/");
		File ret = new File(baseDir);
		String substr = null;
		if (dirs.length >= 1) {
			for (int i = 0; i < dirs.length - 1; i++) {
				substr = dirs[i];
				try {
					// substr.trim();
					substr = new String(substr.getBytes("8859_1"), "GB2312");

				} catch (UnsupportedEncodingException e) {
					L.e(e);
				}
				ret = new File(ret, substr);
				if (!ret.exists())
					ret.mkdirs();
			}

			substr = dirs[dirs.length - 1];
			try {
				// substr.trim();
				substr = new String(substr.getBytes("8859_1"), "GB2312");

			} catch (UnsupportedEncodingException e) {
				L.e(e);
			}

			ret = new File(ret, substr);

			return ret;
		}
		return ret;

	}
	
	public  ArrayList<Li> parseHtml(String folder)
			throws FileNotFoundException, IOException {
		ArrayList<Li> pagers = null;
		if(U.isNull(folder)){
			return pagers;
		}
		File doc = FileHelper.getSDCardFile(folder);
		if (U.isNull(doc)) {
			return pagers;
		}
		File file = FileHelper.searchFile(doc, "index.html");
		if (U.notNull(file) && file.exists()) {
			String html = FileHelper.getFromInputStream(new FileInputStream(
					file));
			Document content = Jsoup.parse(html);
			Elements element = content.getElementsByTag("ul");
			if (U.notNull(element) && !element.isEmpty()) {
				for (Element ul : element) {
					Elements lis = ul.getElementsByTag("li");
					if (U.notNull(lis) && !lis.isEmpty()) {
						pagers = new ArrayList<Li>(lis.size());
						Li ad;
						String type = null;
						for (Element li : lis) {
							ad = null ;
							type = li.attr("type");
							if(U.notNull(type)){
								ad = new Li();
								if("video".equals(type)){
									ad.type = Li.TYPE_VIDEO;
								}
								if("image".equals(type)){
									ad.type = Li.TYPE_IMAGE;
								}
						
							}else{
								continue;
							}
							
							Elements images = li.getElementsByTag("img");
							if (U.notNull(images) && !images.isEmpty()) {
								Element image = images.first();
								File s = new File(doc, image.attr("src"));
								if (s.exists() && U.notNull(ad)) {
									ad.img = s;
									ad.duration = U.toInt((li.attr("time")));
									
								}
							}
							Elements videos = li.getElementsByTag("video");
							if (U.notNull(videos) && !videos.isEmpty()) {
								Element video = videos.first();
								File f = new File(doc, video.attr("src"));
								if (f.exists() && U.notNull(ad)) {									
									ad.video = f;
								}
							}
							if(U.notNull(ad))pagers.add(ad);
						}

					}

				}
			}
		}
		return pagers;

	}
	
	
	public  void destory(){
		APP.getInstance().isDownloading = false;
		mDownTask = null;
 		mZipTask = null;
 		handler.removeCallbacksAndMessages(null);
 		handler = null;
	}

}
